#include <iostream>
#include <memory>
using namespace std;

/******************************
 *  Proxy(代理)模式 : 通过代理类，来控制实际对象的访问权限
 */

class VideoSite   
{
public:
    // 针对不同身份的用户，具备不同的访问权限
    virtual void freeMovie() = 0;     
    virtual void vipMovie() = 0;
    virtual void ticketMovie() = 0;
};

class FixBugVideoSite : public VideoSite     // 委托类
{
public:
    void freeMovie() { cout << "可以观看免费电影\n"; }
    void vipMovie() { cout << "可以观看vip电影\n"; }
    void ticketMovie() { cout << "可以观看付费电影\n"; }
};

// 代理类，对委托类 FixBugVideoSite 进行代理
class FreeVideoSiteProxy : public VideoSite     
{
public:
    FreeVideoSiteProxy() { pVideo = new FixBugVideoSite(); }
    ~FreeVideoSiteProxy() { delete pVideo; }
    void freeMovie() { pVideo->freeMovie(); }
    void vipMovie() { cout << "你不配看vip电影\n"; }
    void ticketMovie() { cout << "你不配看付费电影\n"; }
private:
    VideoSite* pVideo;
};

class VipVideoSiteProxy : public VideoSite     
{
public:
    VipVideoSiteProxy() { pVideo = new FixBugVideoSite(); }
    ~VipVideoSiteProxy() { delete pVideo; }
    void freeMovie() { pVideo->freeMovie(); }
    void vipMovie() { pVideo->vipMovie(); }
    void ticketMovie() { cout << "你不配看付费电影\n"; }
private:
    VideoSite* pVideo;
};

// 通过API, 不关心指向对象所具备的权限，多态会出手
void watchMovie(unique_ptr<VideoSite>& ptr)
{
    ptr->freeMovie();
    ptr->vipMovie();
    ptr->ticketMovie();
}

int main()
{
    unique_ptr<VideoSite> p1(new FreeVideoSiteProxy());
    unique_ptr<VideoSite> p2(new VipVideoSiteProxy());
    watchMovie(p1);
    watchMovie(p2);
    return 0;
}